#include "ActorSerializer.h"
#include <SECore/Ecs/Actor.h>
#include <yaml-cpp/yaml.h>
// #include <SEngine/Util/Util.h>
// #include <SECore/Util.h>
#include <SESerializeYAML/Util.h>
#include <SEngine/Ecs/TypeRegister.h>
#include <yaml-cpp/node/type.h>
#include <SECore/Ecs/Scene.h>
#include <SEngine/Ecs/Components/AllComponents.h>
#include <SEDebug/Log/Log.h>
#include <memory>
#include <iostream>
#include <SESerializeYAML/ComponentSerializer.h>

namespace SEngine
{
    std::string Serializer<Actor>::Serialize(Actor & object)
    {
        YAML::Node node;
        object.ForeachChildren([&node](Actor& child){
            node["Actor"]["Children"].push_back(YAML::Load(child.Serialize()));
        });
        for (auto & [_, comp] : object.m_components) {
            node["Actor"]["Components"][comp->Name()] = YAML::Load(comp->Serialize(AllComponents()));
        }
        return YAMLNodeToString(node);
    }

    void Serializer<Actor>::Deserialize(const std::string& str, Actor & object)
    {
        YAML::Node node = YAML::Load(str);
        for (auto childNode : node["Actor"]["Children"]) {
            auto & child = object.GetScene().CreateActor();
            object.AddChild(child);
            child.Deserialize(YAMLNodeToString(childNode));
        }
        for (auto compNode : node["Actor"]["Components"]) {
            ForeachType([&](auto loader) {
                using CompType = decltype(loader)::Type;
                if (std::string(typeid(CompType).name()) == compNode.first.as<std::string>()) {
                    auto & comp = object.AddComponent<CompType>();
                    comp.Deserialize(YAMLNodeToString(compNode.second));
                }
            }, AllComponents());
        }
    }
} // namespace SEngine
